export class WebSocketClient {
  constructor(url, protocols) {
    this.url = url;
    this.protocols = protocols;
    this.socket = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5; // 最大重连次数
    this.reconnectInterval = 3000; // 重连间隔(毫秒)
    this.reconnectTimer = null;
    this.autoReconnect = true; // 是否自动重连
    this.isExplicitlyClosed = false; // 是否显式关闭连接

    this.callbacks = {
      open: [],
      message: [],
      close: [],
      error: [],
      reconnect: [],
    };
  }

  // 连接 WebSocket
  connect() {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      return;
    }

    this.isExplicitlyClosed = false;
    this.socket = new WebSocket(this.url, this.protocols);

    // 绑定事件处理
    this.socket.onopen = (event) => {
      this.reconnectAttempts = 0; // 重置重连计数器
      this._handleEvent("open", event);
    };

    this.socket.onmessage = (event) => this._handleEvent("message", event);

    this.socket.onclose = (event) => {
      this._handleEvent("close", event);
      if (!this.isExplicitlyClosed && this.autoReconnect) {
        this._scheduleReconnect();
      }
    };

    this.socket.onerror = (event) => {
      this._handleEvent("error", event);
      if (!this.isExplicitlyClosed && this.autoReconnect) {
        this._scheduleReconnect();
      }
    };
  }

  // 发送消息
  send(data) {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(data);
    } else {
      throw new Error("WebSocket 连接未打开");
    }
  }

  // 发送 JSON 消息
  sendJson(data) {
    try {
      const jsonData = JSON.stringify(data);
      this.send(jsonData);
    } catch (error) {
      console.error("JSON 序列化失败:", error);
      throw error;
    }
  }

  // 关闭连接
  close(code, reason) {
    this.isExplicitlyClosed = true;
    this.autoReconnect = false;
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
    if (this.socket) {
      this.socket.close(code, reason);
    }
  }

  // 添加事件监听
  on(event, callback) {
    if (this.callbacks[event]) {
      this.callbacks[event].push(callback);
    }
  }

  // 移除事件监听
  off(event, callback) {
    if (this.callbacks[event]) {
      this.callbacks[event] = this.callbacks[event].filter(
        (cb) => cb !== callback
      );
    }
  }

  // 设置自动重连配置
  setReconnectOptions({ maxAttempts, interval, autoReconnect }) {
    if (maxAttempts !== undefined) {
      this.maxReconnectAttempts = maxAttempts;
    }
    if (interval !== undefined) {
      this.reconnectInterval = interval;
    }
    if (autoReconnect !== undefined) {
      this.autoReconnect = autoReconnect;
    }
  }

  // 计划重连
  _scheduleReconnect() {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.warn(
        `已达到最大重连次数(${this.maxReconnectAttempts})，停止重连`
      );
      return;
    }

    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
    }

    this.reconnectAttempts++;
    const delay =
      this.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1); // 指数退避

    this.reconnectTimer = setTimeout(() => {
      this._notifyReconnectAttempt();
      this.connect();
    }, delay);
  }

  // 通知重连尝试
  _notifyReconnectAttempt() {
    const attemptInfo = {
      attempt: this.reconnectAttempts,
      maxAttempts: this.maxReconnectAttempts,
      nextAttemptDelay:
        this.reconnectInterval * Math.pow(1.5, this.reconnectAttempts),
    };
    this.callbacks.reconnect.forEach((callback) => callback(attemptInfo));
  }

  // 处理事件
  _handleEvent(event, data) {
    if (event === "message" && typeof data.data === "string") {
      try {
        const jsonData = JSON.parse(data.data);
        if (jsonData?.type === "ping") {
          // 忽略ping消息或可以在这里实现pong响应
          return;
        }
        this.callbacks[event].forEach((callback) => callback(jsonData));
      } catch (error) {
        if (data.data === "ping") {
          return;
        }
        // 不是 JSON 格式，按原始数据处理
        this.callbacks[event].forEach((callback) => callback(data.data));
      }
    } else {
      this.callbacks[event].forEach((callback) => callback(data));
    }
  }
}

/* const ws = new WebSocketClient('wss://example.com/ws');

// 配置重连参数
ws.setReconnectOptions({
  maxAttempts: 10,
  interval: 5000,
  autoReconnect: true
});

ws.on('open', () => {
  console.log('连接已建立');
});

ws.on('message', (data) => {
  console.log('收到消息:', data);
});

ws.on('reconnect', (attemptInfo) => {
  console.log(`正在尝试第 ${attemptInfo.attempt} 次重连，共 ${attemptInfo.maxAttempts} 次`);
});

ws.connect();

// 发送消息
ws.sendJson({ type: 'hello', data: 'world' });

// 显式关闭连接(不会触发重连)
// ws.close(); */
